import re

from celery import current_app
from django.conf import settings
from django.http import HttpResponse, JsonResponse
from django.shortcuts import render
from rest_framework.mixins import UpdateModelMixin
from rest_framework.views import APIView
from random import randint
from rest_framework.response import Response
from django_redis import get_redis_connection
from rest_framework.generics import CreateAPIView, RetrieveAPIView, UpdateAPIView
from rest_framework_jwt.views import ObtainJSONWebToken
from django_redis import get_redis_connection

from carts.utils import merge_cart_cookie_to_redis
from celery_tasks.sms.tasks import send_sms_code
from meiduo_mall.libs.captcha.captcha import captcha, Captcha
from users.models import User
from itsdangerous import TimedJSONWebSignatureSerializer
from meiduo_mall.libs.yuntongxun.sms import CCP
from rest_framework_jwt.settings import api_settings
from threading import Thread
from itsdangerous import TimedJSONWebSignatureSerializer as TJS
# def send_sms_code(mobile,sms_code):
#     ccp = CCP()
#     ccp.send_template_sms(mobile, [sms_code, '5'], 1)


# Create your views here.
from users.serializers import UserSerialzier, UserDetailSerialzier, UserEmailSerialzier


class SmsCodeView(APIView):
    """
        发送短信验证
    """

    def get(self, request, mobile):
        #  判断请求间隔是否在60s内
        conn = get_redis_connection('sms_code')
        flag = conn.get('sms_code_flag_%s' % mobile)
        if flag:
            return Response({'error': '请求过于频繁'}, status=403)

        # 1、路由中正则获取手机号
        # 2、生成一个短信验证码
        sms_code = '%06d' % randint(0, 999999)
        print(sms_code)

        # 3、将短信验证码保存在redis缓存中
        # 生成管道对象
        pl = conn.pipeline()
        pl.setex('sms_code_%s' % mobile, 300, sms_code)
        '''
            setex sms_code_137111111 3000 602978
        '''
        pl.setex('sms_code_flag_%s' % mobile, 60, 2)
        pl.execute()

        # 4、发送短信
        # ccp = CCP()
        # ccp.send_template_sms(mobile, [sms_code, '5'], 1)
        # t=Thread(target=send_sms_code,kwargs={'mobile':mobile,'sms_code':sms_code})
        # t.start()

        # 使用celery发送短息
        send_sms_code.delay(mobile, sms_code)

        # 5、返回结果
        return Response({'message': 'ok'})


class UsernameCountView(APIView):
    """
        判断用户名是否重复
    """

    def get(self, request, username):
        # 1、获取用户名
        # 2、查询用户名所对应的用户对象数量
        count = User.objects.filter(username=username).count()
        # 3、返回数量结果
        return Response({'count': count})


class MobileCountView(APIView):
    """
        判断手机号是否重复
    """

    def get(self, request, mobile):
        # 1、获取手机号
        # 2、查询手机号所对应的用户对象数量
        count = User.objects.filter(mobile=mobile).count()
        # 3、返回数量结果
        return Response({'count': count})


class UserView(CreateAPIView):
    """
        注册保存用户信息
    """
    serializer_class = UserSerialzier


class UserDetailView(RetrieveAPIView):
    """
        获取登录用户信息
    """
    queryset = User.objects.all()
    serializer_class = UserDetailSerialzier

    def get_object(self):
        return self.request.user


class UserEmailView(UpdateAPIView):
    """
        更新用户邮箱
    """
    serializer_class = UserEmailSerialzier

    def get_object(self):
        return self.request.user


class EmailVerifyView(APIView):
    """
        邮箱验证
    """

    def get(self, request):
        # 1、获取token值
        token = request.query_params.get('token')
        # 2、解密token进行验证
        try:
            tjs = TimedJSONWebSignatureSerializer(settings.SECRET_KEY, 300)
            token_de = tjs.loads(token)
        except:
            return Response({'error': "错误的token 值"}, status=403)
        # 3、提取用户id和email
        user_id = token_de.get('user_id')
        email = token_de.get('email')
        if user_id is None or email is None:
            return Response({'error': "token值失效"}, status=403)
        # 4、查询用户对象
        try:
            user = User.objects.get(id=user_id, email=email)
        except:
            return Response({'error': "用户不存在"}, status=403)
        # 5、更新邮箱验证状态
        user.email_active = True
        user.save()
        # 6、返回结果
        return Response({'email_active': user.email_active})


class UserLoginView(ObtainJSONWebToken):
    def post(self, request, *args, **kwargs):
        # 执行父类用户校验的方法
        reponse = super().post(request, *args, **kwargs)

        serializer = self.get_serializer(data=request.data)

        if serializer.is_valid():
            # 获取用户对象
            user = serializer.object.get('user') or request.user
            # 合并购物车
            reponse = merge_cart_cookie_to_redis(request, reponse, user)
            return reponse
        return reponse


class UpdatePasswordView(APIView):
    def put(self, request, pk):
        data = request.data
        user = User.objects.get(id=pk)
        if not user.check_password(data['old_password']):
            raise Exception('原密码输入有误')


class ImageCodeView(APIView):
    """
        获取网页的图片验证码
    """

    def get(self, request, image_code_id):
        # 1, 获取参数, 判空
        conn = get_redis_connection('image_code')
        name, text, content = captcha.generate_captcha()

        # 2, 生成图片验证码
        image_code = text
        print(image_code)
        # 3, 保存图片验证码文本信息到redis
        pl = conn.pipeline()
        conn.setex('image_code_%s' % image_code_id, 300, image_code)
        pl.execute()
        # 4, 返回 '图片内容'content 到浏览器
        image = content
        return HttpResponse(image, content_type="image/jpg")


class ImageCode2CountView(APIView):
    """
    图片验证码校验，返回发短信token
    """

    def get(self, request, username):

        # 验证码验证
        # 获取验证码和验证码ID
        image_code = request.query_params.get('text')
        image_code_id = request.query_params.get('image_code_id')
        # 1、建立redis连接
        conn = get_redis_connection('image_code')
        # 2、获取真实的验证码
        real_image_code = conn.get('image_code_%s' % image_code_id)
        # 3、判断是在有效期内
        if not real_image_code:
            return Response({'error': "验证码失效"}, status=400)
        # 4、比对用户输入的和真实验证码
        if image_code.lower() != real_image_code.decode().lower():
            return Response({'error': "验证码错误"}, status=400)
        if 'image_code' == real_image_code.decode():
            conn.delete('image_code_%s' % 'image_code_id')

        # 1、判断username所对应的数据是否是手机号
        try:
            if re.match(r'^1[3-9]\d{9}$', username):
                user = User.objects.get(mobile=username)
            else:
                user = User.objects.get(username=username)
        except:
            user = None
        # 生成token值
        data = {'username': user.username, 'mobile': user.mobile}
        tjs = TJS(settings.SECRET_KEY, 300)
        token = tjs.dumps(data).decode()
        print(user.mobile)
        print(token)
        # 1、获取手机号
        # 2、查询手机号所对应的用户对象数量
        count = User.objects.filter(mobile=user.mobile).count()
        # 3、返回数量结果

        return Response({
            "mobile": user.mobile,
            "access_token": token,
            'count': count,
        })


class SmsCodeRellsetView(APIView):
    """
        发送 短信验证
    """

    def get(self, request):
        # 1、获取token值
        token = request.query_params.get('access_token')
        # 2、解密token进行验证
        try:
            tjs = TimedJSONWebSignatureSerializer(settings.SECRET_KEY, 300)
            token_de = tjs.loads(token)
        except:
            return Response({'error': "错误的token 值"}, status=403)
        # 3、提取用户id和mobile
        username = token_de.get('username')
        mobile = token_de.get('mobile')
        if username is None or mobile is None:
            return Response({'error': "token值失效"}, status=403)
        # 4、查询用户对象
        try:
            user = User.objects.get(username=username, mobile=mobile)
        except:
            return Response({'error': "用户不存在"}, status=403)
        conn = get_redis_connection('sms_code')
        flag = conn.get('sms_code_flag_%s' % mobile)
        if flag:
            return Response({'error': '请求过于频繁'}, status=403)
        # 1、路由中正则获取手机号
        # 2、生成一个短信验证码
        sms_code = '%06d' % randint(0, 999999)
        print(sms_code)
        # 3、将短信验证码保存在redis缓存中
        # 生成管道对象
        pl = conn.pipeline()
        pl.setex('sms_code_%s' % mobile, 300, sms_code)
        pl.setex('sms_code_flag_%s' % mobile, 60, 2)
        pl.execute()

        # 使用celery发送短息
        send_sms_code.delay(mobile, sms_code)

        # 5、返回结果
        return Response({'message': 'ok'})


class SmsCode2VerifyView(APIView):
    """
    短信验证码校验，返回改密码token
    """

    def get(self, request, username):

        # 验证码验证
        # 获取验证码和验证码ID
        sms_code = request.query_params.get('sms_code')
        # 1、判断username所对应的数据是否是手机号
        try:
            if re.match(r'^1[3-9]\d{9}$', username):
                user = User.objects.get(mobile=username)
            else:
                user = User.objects.get(username=username)
        except:
            user = None

        mobile = user.mobile
        # 1、建立redis连接
        conn = get_redis_connection('sms_code')
        # 2、获取真实的验证码
        real_sms_code = conn.get('sms_code_%s' % mobile)
        # 3、判断是在有效期内
        if not real_sms_code:
            return Response({'error': "验证码失效"}, status=400)
        # 4、比对用户输入的和真实验证码
        if sms_code != real_sms_code.decode():
            return Response({'error': "验证码错误"}, status=400)
        if sms_code == real_sms_code.decode().lower():
            conn.delete('sms_code_%s' % 'mobile')

        # 生成token值
        data = {'user_id': user.id, 'mobile': user.mobile}
        tjs = TJS(settings.SECRET_KEY, 300)
        token = tjs.dumps(data).decode()
        print(user.mobile)
        print(token)

        return Response({
            "user_id": user.id,
            "access_token": token,
        })




class UserResetView(UpdateAPIView):
    """
    改密码
    """

    def post(self, request, pk):
        data = request.data

        # # 1、获取token值
        token = data['access_token']
        # # 2、解密token进行验证
        try:
            tjs = TimedJSONWebSignatureSerializer(settings.SECRET_KEY, 300)
            token_de = tjs.loads(token)
        except:
            return Response({'error': "错误的token 值"}, status=403)
        # 3、提取用户id和mobile
        user_id = token_de.get('user_id')
        mobile = token_de.get('mobile')
        if user_id is None or mobile is None:
            return Response({'error': "token值失效"}, status=403)
        # 4、查询用户对象
        try:
            user = User.objects.get(id=user_id, mobile=mobile)
        except:
            return Response({'error': "用户不存在"}, status=403)
        user = User.objects.get(id=pk)

        if data['password'] != data['password2']:
            raise Exception('两次密码不一致，请重新输入')
        user.set_password(data['password'])
        user.save()
        return Response({'message': 'ok'})
        # serializer_class = PasswordChange

        # def get_object(self):
        #
        #     return self.request.user
